
`include "common_header.verilog"

//  *************************************************************************
//  File : sd_ln_blk_40g_64b.v
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited.
//  Copyright (c) 2010 MorethanIP
//  Muenchner Strasse 199, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Denis Poverennyy
//  info@morethanip.com
//  *************************************************************************
//  Description : The Serdes Lane Block start writing PCS blocks into 
//  the Deskew Buffer as soon as at least one Alignment marker is detected.
//  Version     : $Id: sd_ln_blk_40g_64b.v,v 1.6 2015/03/22 12:30:38 dk Exp $
//  *************************************************************************

module sd_ln_blk_40g_64b (

        reset_sd_rx_clk,
        sd_rx_clk,
        sd_rx_clk_ena,
        sd_rx,
        signal_det,
        sw_reset,
        disable_mld,
        vl_0_enc,
        vl_1_enc,
        vl_2_enc,
        vl_3_enc,
        pcs_block,
        pcs_block_vl,
        block_lock
 `ifdef MTIPPCS_FEC_ENA
        ,
        fec_ena,
     `ifdef MTIPPCS82_EEE_ENA
        fec_fastlock,
     `endif
     `ifdef MTIPPCS_FECERR_ENA                
        fec_err_ena,
     `endif
        fec_locked,
        fec_cerr,
        fec_ncerr
  `endif
  `ifdef MTIPPCS82_EEE_ENA
        ,
        rx_mode_quiet,
        ram_period
  `endif 
                        );


input                   reset_sd_rx_clk;        //  async active high reset
input                   sd_rx_clk;              //  Serdes clock
input                   sd_rx_clk_ena;          //  serdes clock enable
input   [66 - 1:0]      sd_rx;                  //  SERDES data input
input                   signal_det;             //  if low SERDES' signals are not valid
input                   sw_reset;               //  on sw reset search for a new Alignment Marker starts
input                   disable_mld;            //  disable MLD (10G/25G mode setting)

input   [23:0]          vl_0_enc;               //  Marker pattern for PCS Virtual Lane 0
input   [23:0]          vl_1_enc;               //  Marker pattern for PCS Virtual Lane 1
input   [23:0]          vl_2_enc;               //  Marker pattern for PCS Virtual Lane 2
input   [23:0]          vl_3_enc;               //  Marker pattern for PCS Virtual Lane 3


output  [66:0]          pcs_block;              //  66 Bit Block with sync header (2 lsb) plus sync block
output                  pcs_block_vl;           //  used as a write enable into the deskew buffer 
output                  block_lock;             //  block lock in the serdes domain

`ifdef MTIPPCS_FEC_ENA
input                   fec_ena; 
`ifdef MTIPPCS82_EEE_ENA
input                   fec_fastlock;           //  if set, allows fast FEC lock acquisition procedure. The signal set when
                                                //  LPI SM in the RX_WAKE state
`endif
`ifdef MTIPPCS_FECERR_ENA
input                   fec_err_ena;
`endif
output                  fec_locked; 
output                  fec_cerr; 
output                  fec_ncerr; 
`endif

`ifdef MTIPPCS82_EEE_ENA
input                   rx_mode_quiet;           // Indication that the remote has disabled its transmitter
input                   ram_period;              // if set the RAM is expected;

`endif

//-------------------------------------
//      Output Signals
//-------------------------------------
wire                    block_lock; 
wire    [66:0]          pcs_block; 
wire                    pcs_block_vl; 
`ifdef MTIPPCS_FEC_ENA
wire                    fec_locked; 
wire                    fec_cerr; 
wire                    fec_ncerr;
`endif
//-------------------------------------
// Internal Signals
//-------------------------------------
wire                    pcs_block_64_bit_val;   // 64 Bit block and Sync header valid
wire    [63:0]          pcs_block_64_bit;       // 64 Bit PCS block
wire    [63:0]          pcs_block_64_bit_muxed; // either input data or reverse one, depending on the ram_period                  
wire    [1:0]           sync_header;            // Sync header                       
wire                    marker_det;             // any alignment marker detected
wire    [65:0]          sd_rx_66_blk_sync_din;  // Data input to the Block sync module (FEC output)  
wire                    gctl_stop;              //  stop block sync bit slip function
wire                    disable_mld_n;          //  disable MLD (10G/25G mode setting) - inverse

`ifdef MTIPPCS_FEC_ENA
wire    [65:0]          fec_dout;               // Data output from the FEC Module
`endif

wire block_lock_int;

`ifdef MTIPPCS_FEC_ENA          

fec_dec_1l_xlc U_FEC_DET_1L (
        .reset          (reset_sd_rx_clk),
        .clk            (sd_rx_clk),
        .clk_ena        (sd_rx_clk_ena),
`ifdef MTIPPCS82_EEE_ENA
        .fec_fastlock   (fec_fastlock),
`endif
        .fec_din        (sd_rx),
        .fec_ena        (fec_ena),
`ifdef MTIPPCS_FECERR_ENA
         .fec_err_ena   (fec_err_ena),
         .fec_mode_xlc  (1'b 0),                // mode of operation (0=10G, 1=40G/100G) 1 corrupts all sync headers in a burst.
         .sw_reset      (sw_reset),
`endif               
        .fec_locked     (fec_locked),
        .fec_cerr       (fec_cerr),
        .fec_ncerr      (fec_ncerr),
        .fec_dout       (fec_dout));
          
          
          

mtip_xsync      #(1) U_FECSYNC (
        .reset          (reset_sd_rx_clk),
        .clk            (sd_rx_clk),
        .data_in        (fec_ena),
        .data_s         (gctl_stop));           // no need to do bitslipping when fec is enabled as fec does it already.
          
assign  sd_rx_66_blk_sync_din = fec_dout;

`else

assign  gctl_stop = 1'b 0;
assign  sd_rx_66_blk_sync_din = sd_rx;

`endif

assign  disable_mld_n = ~disable_mld;

// =============================================================

block_sync_1040 U_BLOCK_SYNC (

        .reset          (reset_sd_rx_clk),
        .clk            (sd_rx_clk),
        .ck_ena         (sd_rx_clk_ena),
        .mode40         (disable_mld_n),        // When not disabled use Clause 82 behavior.
        .gctl_stop      (gctl_stop),            // when FEC is enabled disable slipping as FEC will do alignment already
        .sig_det        (signal_det),
        .data_in        (sd_rx_66_blk_sync_din),
        .block_lock     (block_lock_int),           //  BLock Lock state reached
        .sync_lost      (),                     //  Sync lost pulse
        .data_valid     (),
        .data_valid_scr (pcs_block_64_bit_val), //  64 Bit block and Sync header valid 
        .data_out       (pcs_block_64_bit),     //  64 Bit PCS block
        .sh_out         (sync_header));


assign block_lock = block_lock_int;

`ifdef MTIPPCS82_EEE_ENA
assign pcs_block_64_bit_muxed = (ram_period == 1'b0)? pcs_block_64_bit: ~pcs_block_64_bit;

`else

assign pcs_block_64_bit_muxed = pcs_block_64_bit;


`endif



p8264_first_am_detect U_FIRST_AM_DET (
        .reset          (reset_sd_rx_clk),
        .clk            (sd_rx_clk),
        .data_val       (pcs_block_64_bit_val),
        .block_lock     (block_lock_int),
        .sw_reset       (sw_reset),
        .vl_0_enc       (vl_0_enc),
        .vl_1_enc       (vl_1_enc),
        .vl_2_enc       (vl_2_enc),
        .vl_3_enc       (vl_3_enc),
        .data_in        (pcs_block_64_bit_muxed),
        .sh_in          (sync_header),
        .marker_det     (marker_det),
        .vl_match_num   ());
          
          
assign pcs_block = {block_lock_int, pcs_block_64_bit, sync_header};






`ifdef MTIPPCS82_EEE_ENA
assign pcs_block_vl = (marker_det | disable_mld) & pcs_block_64_bit_val & !rx_mode_quiet; 
`else
assign pcs_block_vl = (marker_det | disable_mld) & pcs_block_64_bit_val; 
`endif


endmodule // module sd_ln_blk_40g_64b

